import { addLoading, cancelLoading, handleBusinessError, handleResponseError, handleServiceResult, handleRefreshToken } from '@/request/http/handle.js'
import { createDiscreteApi } from 'naive-ui'
import { DEFAULT_ALOVA_OPTIONS, DEFAULT_BACKEND_OPTIONS, ERROR_STATUS } from './config.js'
import { useAuthStore } from '@/stores/main.js'
import { storage } from '@/utils/storage.js'

const { message, notification, loadingBar } = createDiscreteApi([
  'message',
  'dialog',
  'notification',
  'loadingBar',
])

/**
 * @description: 封装fetch请求
 * @param {string} url - 请求地址
 * @param {object} options - fetch选项
 * @param {boolean} needToken - 是否需要token
 * @param {boolean} showLoading - 是否显示loading
 * @return {Promise} - 返回处理后的响应数据
 */
export async function fetchRequest(url, options = {}, needToken = true, showLoading = true) {
  // 创建基础配置
  const config = {
    method: options.method || 'GET',
    headers: {
      'Content-Type': 'application/json',
      ...options.headers,
    },
    credentials: 'include',
    timeout: options.timeout || DEFAULT_ALOVA_OPTIONS.timeout,
    ...options,
  }

  // 添加token
  if (needToken) {
    const token = storage.get('accessToken')
    if (token) {
      config.headers.Authorization = `Bearer ${token}`
    }
  }

  // 处理请求参数
  if (config.method.toUpperCase() === 'GET') {
    if (options.params) {
      const params = new URLSearchParams()
      Object.keys(options.params).forEach(key => {
        params.append(key, options.params[key])
      })
      url = `${url}?${params.toString()}`
    }
  } else {
    if (options.data) {
      config.body = JSON.stringify(options.data)
    }
  }

  // 显示loading
  if (showLoading) {
    addLoading()
  }

  try {
    // 创建fetch请求
    const controller = new AbortController()
    const { signal } = controller
    config.signal = signal

    // 设置超时
    const timeoutId = setTimeout(() => controller.abort(), config.timeout)

    const response = await fetch(url, config)
    clearTimeout(timeoutId)

    if (!response.ok) {
      // 处理HTTP错误状态码
      if (response.status === 401) {
        // token过期，尝试刷新
        await handleRefreshToken()
        // 刷新后重试请求
        return fetchRequest(url, options, needToken, showLoading)
      }
      const error = handleResponseError(response)
      throw error
    }

    // 解析JSON响应
    const data = await response.json()

    // 处理业务逻辑错误
    const { codeKey, successCode } = DEFAULT_BACKEND_OPTIONS
    if (data[codeKey] !== successCode) {
      const error = handleBusinessError(data, DEFAULT_BACKEND_OPTIONS)
      throw error
    }

    // 返回处理后的成功结果
    return handleServiceResult(data)
  } catch (error) {
    // 处理请求异常
    if (error.name === 'AbortError') {
      throw { message: '请求超时', code: 408 }
    }
    throw error
  } finally {
    // 隐藏loading
    if (showLoading) {
      cancelLoading(false)
    }
  }
}

/**
 * @description: 创建fetch实例
 * @param {object} options - 配置选项
 * @return {object} - 返回包含各种请求方法的对象
 */
export function createFetchInstance(options = {}) {
  const baseURL = options.baseURL || DEFAULT_ALOVA_OPTIONS.baseURL

  const instance = {
    // GET请求
    get(url, params = {}, fetchOptions = {}, needToken = true, showLoading = true) {
      return fetchRequest(`${baseURL}${url}`, {
        method: 'GET',
        params,
        ...fetchOptions,
      }, needToken, showLoading)
    },

    // POST请求
    post(url, data = {}, fetchOptions = {}, needToken = true, showLoading = true) {
      return fetchRequest(`${baseURL}${url}`, {
        method: 'POST',
        data,
        ...fetchOptions,
      }, needToken, showLoading)
    },

    // PUT请求
    put(url, data = {}, fetchOptions = {}, needToken = true, showLoading = true) {
      return fetchRequest(`${baseURL}${url}`, {
        method: 'PUT',
        data,
        ...fetchOptions,
      }, needToken, showLoading)
    },

    // DELETE请求
    delete(url, params = {}, fetchOptions = {}, needToken = true, showLoading = true) {
      return fetchRequest(`${baseURL}${url}`, {
        method: 'DELETE',
        params,
        ...fetchOptions,
      }, needToken, showLoading)
    },

    // 原始fetch方法
    request: fetchRequest,
  }

  return instance
}
